home *** CD-ROM | disk | FTP | other *** search
- /*
- FezEdit: Frame-Evading Zoomrects Editor
-
- by Douglas McKenna
- (c) Copyright 1994 All rights reserved.
-
- Mathemaesthetics, Inc.
- PO Box 298 • Boulder • CO • 80306-0298 • USA
-
- Submitted as a hack and a half for MacHack, June 24, 1994
- Winner (by popular acclaim) of Best Hack of the Contest
-
- Permission is granted to use this code in any non-commercial product.
- Please contact the author for prior written approval for use in any
- commercial or shareware product.
-
- This file contains the shell application for creating window's with a
- double-clickable and dragable widget icon in them that opens into another
- window. This provides a testbed for the FEZ routines, described in the
- accompanying file, "FEZ.c".
- */
-
-
- #include "Main.h"
- #include "Utilities.h"
- #include "FEZ.h"
-
- #define kDefaultPosition NIL
-
- /* Global variables for whole app */
-
- SysEnvRec thisMac;
-
- /* Global variables for this file's routines only */
-
- static EventRecord myEvent;
- static int appleEventsOK,quitting,firstTime=TRUE;
- static MenuHandle appleMenu,fileMenu,demoMenu,optionsMenu,editMenu;
- static MenuHandle windowMenu,openWindowMenu,closeWindowMenu;
- static CIconHandle fezHat,fezHatSelected;
-
- static WindowPtr windows[MAXWINDOWS];
- static Rect windowPosition[MAXWINDOWS];
- static Rect windowWidgetPosition[MAXWINDOWS];
- static short zoomStyle,lineThick,speed,theDemo,qSize;
- static Rect stdWidgetPosition = { 50, 50, 50+WIDGETHEIGHT, 50+WIDGETWIDTH };
-
- static AEEventHandlerUPP odocUPP;
- static AEEventHandlerUPP oappUPP;
- static AEEventHandlerUPP pdocUPP;
- static AEEventHandlerUPP quitUPP;
-
-
- /* Prototypes for local routines */
-
- void main(void);
- void Initialize(void);
-
- void InstallCoreEventHandlers(void);
- void DoHighLevelEvent(EventRecord *evt);
- pascal OSErr HandleOAPP(AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- pascal OSErr HandleODOC(AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- pascal OSErr HandlePDOC(AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- pascal OSErr HandleQUIT(AppleEvent *appleEvent, AppleEvent *reply, long refcon);
- int DoOpenApplication(void);
- OSErr MyGotRequiredParams(AppleEvent *appleEvent);
-
- int MainEvent(void);
- int DoMouseDown(short modifiers);
- void DoContentClick(WindowPtr aWindow, Point p);
- void SelectWidget(WidgetHandle item, int selected);
- int DoMouseUp(void);
- void DoActivate(WindowPtr w, int activ);
- void DoUpdate(WindowPtr w);
- void UpdateAllWindows(void);
- Rect * SetInteriorClipping(WindowPtr w);
- void RestoreInteriorClipping(WindowPtr w);
- int DoKeyDown(void);
- void DoGrow(WindowPtr w);
- int DoMenu(long choice, short modifiers);
- void RebuildDemoMenu(void);
- void InstallDemo(short i);
- void RecordCurrentDemo(short modifiers);
-
- int IsDoubleClick(Point *pt, long *time, int tol);
- Rect *StaggeredWindowBounds(short index);
- short NextFreeWindowIndex(void);
- WindowPtr NewWidgetWindow(void);
- WindowPtr CreateWidgetWindow(short index, Rect *bounds, Rect *widgetSpot, int show);
- void DoAppleMenu(int choice);
- void DispatchEvent(EventRecord *evt);
- void FixMenus(void);
- WidgetHandle CloseZoom(WindowPtr w);
- WidgetHandle CloseWidgetWindow(WindowPtr w);
- short RecordPositions(WindowPtr w);
- WindowPtr OpenWidgetWindow(WindowPtr w);
- void DrawWidget(WidgetHandle item);
- void CloseAllWindows(int reset);
-
- void main()
- {
- Initialize();
-
- while (MainEvent()) ; /* Life until event-ual death */
- }
-
-
- void Initialize()
- {
-
- /* Usual Mac Toolbox startup calls */
-
- MaxApplZone();
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitCursor();
- InitMenus();
- InitDialogs(0L);
- FlushEvents(everyEvent, 0 );
-
- /* Figure out what's legal on this machine */
-
- SysEnvirons(1,&thisMac);
- appleEventsOK = (thisMac.systemVersion >= 0x0700); /* Should be using Gestalt */
-
- /* Install Apple Event stuff */
-
- if (appleEventsOK)
- InstallCoreEventHandlers();
-
- /* Install menus */
-
- appleMenu = GetMenu(appleMenuID);
- AddResMenu(appleMenu,'DRVR');
- InsertMenu(appleMenu,0);
- fileMenu = GetMenu(fileMenuID);
- InsertMenu(fileMenu,0);
- openWindowMenu = GetMenu(openWindowMenuID);
- InsertMenu(openWindowMenu,-1);
- closeWindowMenu = GetMenu(closeWindowMenuID);
- InsertMenu(closeWindowMenu,-1);
-
- editMenu = GetMenu(editMenuID);
- InsertMenu(editMenu,0);
- optionsMenu = GetMenu(optionsMenuID);
- InsertMenu(optionsMenu,0);
- demoMenu = GetMenu(demoMenuID);
- InsertMenu(demoMenu,0);
- windowMenu = GetMenu(windowMenuID);
- InsertMenu(windowMenu,0);
-
- zoomStyle = OM_NoZooms;
- CheckItem(optionsMenu,zoomStyle,TRUE);
- theDemo = DM_None;
- CheckItem(demoMenu,theDemo,TRUE);
- lineThick = 1;
- speed = 1;
- qSize = 4;
-
- RebuildDemoMenu();
-
- DrawMenuBar();
-
- /* Do pre-allocations */
-
- fezHat = GetCIcon(fezHatColorIconID);
- if (fezHat == NIL) ExitToShell();
- fezHatSelected = GetCIcon(fezHatSelectedID);
- if (fezHatSelected == NIL) ExitToShell();
- }
-
- /*
- * Install the addresses of the functions that the AppleEvent manager will
- * call when any of the standard core events come in over the transom.
- */
-
- static void InstallCoreEventHandlers()
- {
- OSErr err;
-
- oappUPP = NewAEEventHandlerProc(HandleOAPP);
- odocUPP = NewAEEventHandlerProc(HandleODOC);
- pdocUPP = NewAEEventHandlerProc(HandlePDOC);
- quitUPP = NewAEEventHandlerProc(HandleQUIT);
-
- err = AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,oappUPP,0,FALSE);
- if (err) goto broken;
- err = AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,odocUPP,0,FALSE);
- if (err) goto broken;
- err = AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,pdocUPP,0,FALSE);
- if (err) goto broken;
- err = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,quitUPP,0,FALSE);
- broken:
- if (err) {
- }
- }
-
- pascal OSErr HandleOAPP(AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- OSErr err = noErr, keepGoing = TRUE;
-
- err = MyGotRequiredParams(appleEvent);
- if (!err)
- keepGoing = DoOpenApplication();
-
- return(err);
- }
-
- /*
- * Check to see that all required parameters have been retrieved (IM 6-47)
- */
-
- static OSErr MyGotRequiredParams(AppleEvent *appleEvent)
- {
- DescType returnedType;
- Size actualSize;
- OSErr err;
-
- err = AEGetAttributePtr(appleEvent,keyMissedKeywordAttr,typeWildCard,
- &returnedType,NIL,0,&actualSize);
- if (err == errAEDescNotFound) return(noErr);
- if (!err) err = errAEEventNotHandled;
-
- return(err);
- }
-
- static int DoOpenApplication()
- {
- int keepGoing = TRUE;
-
- return(keepGoing);
- }
-
- pascal OSErr HandleODOC(AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- OSErr err = noErr;
- long iFile,nFiles,numErrs=0;
- Size actualSize;
- AEKeyword keywd;
- DescType returnedType;
- AEDescList docList;
- FSSpec theFile;
-
- err = AEGetParamDesc(appleEvent, keyDirectObject, typeAEList, &docList);
-
- err = MyGotRequiredParams(appleEvent);
- if (!err) {
- AECountItems(&docList,&nFiles);
- for (iFile=1; iFile<=nFiles; iFile++) {
- err = AEGetNthPtr(&docList,iFile,typeFSS,&keywd,&returnedType,
- (Ptr)&theFile,sizeof(FSSpec),&actualSize);
- if (err) {
- break;
- }
- else {
- }
- }
- }
-
- AEDisposeDesc(&docList);
-
- return(err);
- }
-
- pascal OSErr HandlePDOC(AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- short err;
-
- err = HandleODOC(appleEvent,reply,refcon);
- return(err);
- }
-
- pascal OSErr HandleQUIT(AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- int keepGoing = DoMenu(FM_Quit,0);
- quitting = !keepGoing;
-
- return(keepGoing);
- }
-
-
- /*
- * Process next event, return TRUE if okay to continue
- */
-
- int MainEvent()
- {
- int gotOne;
- static int lastWasNull = FALSE;
-
- gotOne = WaitNextEvent(everyEvent,&myEvent,0,NIL);
-
- if (gotOne) {
- FixMenus();
- DispatchEvent(&myEvent);
- lastWasNull = FALSE;
- }
- else {
- /* Null event */
- SetCursor(&qd.arrow);
- if (!lastWasNull) FixMenus();
- lastWasNull = TRUE;
- }
-
- return(!quitting);
- }
-
- /*
- * Figure out what kind of event we've gotten, and deal with it
- */
-
- void DispatchEvent(EventRecord *evt)
- {
- WindowPtr w; short result;
-
- quitting = FALSE;
-
- switch (evt->what) {
- case mouseDown:
- quitting = DoMouseDown(evt->modifiers);
- break;
- case mouseUp:
- quitting = DoMouseUp();
- break;
- case keyDown:
- case autoKey:
- quitting = DoKeyDown();
- break;
- case activateEvt:
- w = (WindowPtr)evt->message;
- DoActivate(w,(myEvent.modifiers & activeFlag)!=0);
- break;
- case updateEvt:
- w = (WindowPtr)evt->message;
- DoUpdate(w);
- break;
-
- case diskEvt:
- result = HiWord(myEvent.message);
- if (result) {
- Point corner;
- /* ??? Can dialog box be centered */
- /* There doesn't appear to be a */
- /* DLOG resource for this one. */
- /* Location (112,80) is the value */
- /* used by Finder 6.1. */
- SetPt(&corner, 112, 80);
- result = DIBadMount(corner, myEvent.message);
- }
- break;
-
- case app4Evt:
- switch(myEvent.message >> 24) {
- case mouseMovedMessage:
- break;
- case suspendResumeMessage:
- w = FrontWindow();
- if (w)
- DoActivate(w,(myEvent.message & 1) != 0);
- break;
- }
- break;
-
- case kHighLevelEvent:
- DoHighLevelEvent(&myEvent);
- break;
-
- default:
- break;
- }
- }
-
- static void DoHighLevelEvent(EventRecord *evt)
- {
- OSErr err = noErr;
-
- /* No high level events supported yet except for the core events */
-
- if (evt->message == (long)kCoreEventClass) {
- err = AEProcessAppleEvent(evt);
- }
- }
-
- /*
- * Call this for an activate/deactivate event
- */
-
- void DoActivate(WindowPtr w, int activ)
- {
- SetPort(w);
- DrawGrowIcon(w);
- }
-
- /*
- * Call this to redraw contents of given window. In this testbed, all windows
- * are the same.
- */
-
- void DoUpdate(WindowPtr w)
- {
- WidgetHandle item;
-
- PushPort(w);
- BeginUpdate(w);
-
- DrawGrowIcon(w);
-
- SetInteriorClipping(w);
-
- item = (WidgetHandle)GetWRefCon(w);
- DrawWidget(item);
-
- RestoreInteriorClipping(w);
-
- EndUpdate(w);
- PopPort();
- }
-
- /*
- * Clip the window to its content region within scroll bar bounds. Delivers a pointer
- * to the clipping rectangle.
- */
-
- Rect *SetInteriorClipping(WindowPtr w)
- {
- static Rect clipper;
-
- clipper = w->portRect;
- clipper.right -= SCROLLBARWIDTH-1;
- clipper.bottom -= SCROLLBARWIDTH-1;
- ClipRect(&clipper);
-
- return(&clipper);
- }
-
- /*
- * Restore the current window's clipping region to whatever it was when
- * when PushContent was called.
- */
-
- void RestoreInteriorClipping(WindowPtr w)
- {
- ClipRect(&w->portRect);
- }
-
- /*
- * Draw the window's widget at its current position. The handle to the window widget
- * is always in the refCon field, and it's always defined.
- */
-
- void DrawWidget(WidgetHandle item)
- {
- Rect position;
-
- position = (*item)->position; // Local coordinates
- PlotCIcon(&position,(*item)->isSelected ? fezHatSelected : fezHat);
- }
-
- /*
- * Call this for a mouse up event
- */
-
- int DoMouseUp()
- {
- return(FALSE);
- }
-
- /*
- * Call this for a mouse down click anywhere
- */
-
- int DoMouseDown(short modifiers)
- {
- short part; Point p; int done = FALSE;
- WindowPtr aWindow;
-
- p = myEvent.where;
- part = FindWindow(p,&aWindow);
- if (aWindow == NIL) {
- switch(part) {
- case inDesk:
- break;
- case inMenuBar:
- done = DoMenu(MenuSelect(p),modifiers);
- break;
- }
- }
- else {
- if (aWindow!=FrontWindow() && part!=inGrow) {
- SelectWindow(aWindow);
- }
- else {
- switch(part) {
- case inContent:
- DoContentClick(aWindow,p);
- break;
- case inGoAway:
- if (TrackGoAway(aWindow,p)) {
- if (modifiers & optionKey)
- CloseAllWindows(FALSE);
- else {
- CloseWidgetWindow(aWindow);
- }
- }
- break;
- case inZoomIn:
- case inZoomOut:
- if (TrackBox(aWindow,p,part)) {
- PushPort(aWindow);
- EraseRect(&aWindow->portRect);
- ZoomWindow(aWindow,part,TRUE);
- DrawGrowIcon(aWindow);
- InvalRect(SetInteriorClipping(aWindow));
- RestoreInteriorClipping(aWindow);
- PopPort();
- }
- break;
- case inSysWindow:
- SystemClick(&myEvent,aWindow);
- break;
- case inDrag:
- DragWindow(aWindow,p,&qd.screenBits.bounds);
- break;
- case inGrow:
- DoGrow(aWindow);
- break;
- }
- }
- }
- return(done);
- }
-
- /*
- * Deal with a mouse down click in the window's content region at the global
- * coordinate in given point.
- */
-
- void DoContentClick(WindowPtr aWindow, Point p)
- {
- short dx,dy; long now; Rect rect,*clip; OSErr err;
- WidgetHandle item;
- GWorldPtr offscreen,saveWorld; PixMapHandle pm;
- GDHandle saveGDevice;
-
- // Get the widget in window, and its position
-
- item = (WidgetHandle)GetWRefCon(aWindow);
- rect = (*item)->position;
- GlobalToLocal(&p);
-
- // Don't overwrite scroll bar lines when dragging, selecting, or deselecting
- clip = SetInteriorClipping(aWindow);
-
- // If click is on widget, select it and entertain a drag or double-click
- // otherwise, deselect widget
-
- if (PtInRect(p,&rect)) {
- now = TickCount();
- if (IsDoubleClick(&p,&now,2)) {
- OpenWidgetWindow(aWindow);
- }
- else {
- // First click always selects item if not already selected
- SelectWidget(item,TRUE);
-
- if (StillDown()) {
-
- // Prepare for a drag: use an offscreen graphics world to avoid flicker
- // If no offscreen world allocated, then we'll draw directly to screen
- // since both screen and offscreen will be using the same coordinates
- // Note that we could use temporary memory here, since we'll be throwing
- // it all away as soon as user lets up the mouse.
-
- GetGWorld(&saveWorld,&saveGDevice);
- err = NewGWorld(&offscreen,0,clip,NIL,NIL,noNewDevice);
- if (err == noErr) {
- SetGWorld(offscreen,NIL);
- pm = GetGWorldPixMap(offscreen);
- LockPixels(pm);
- EraseRect(clip);
- }
- else
- SysBeep(1);
-
- HideCursor(); // So cursor doesn't flicker during drag
-
- while (WaitMouseUp()) {
- Point newPt;
-
- // Get new mouse position in window's local coordinates
- PushPort(aWindow);
- GetMouse(&newPt);
- PopPort();
-
- if (!EqualPt(p,newPt)) {
- // Mouse has moved to a new position: use offset to move widget
- dx = newPt.h - p.h;
- dy = newPt.v - p.v;
- EraseRect(&rect); // Erase old icon bounds
- OffsetRect(&rect,dx,dy); // Move icon to new position
- (*item)->position = rect;
- DrawWidget(item); // Redraw it in current world
- // And update screen if above drawing was into offscreen world
- if (err == noErr)
- CopyBits((BitMap *)*pm,&aWindow->portBits,clip,clip,srcCopy,NIL);
- // Move to new point and wait until another change in mouse position
- p = newPt;
- }
- }
- ShowCursor();
- // Drag done: clean up
- if (err == noErr) {
- UnlockPixels(pm);
- DisposeGWorld(offscreen);
- }
- SetGWorld(saveWorld,saveGDevice);
- }
- }
- }
- else {
- SelectWidget(item,FALSE); // Deselect it
- }
-
- // Allow full content area to be drawn into again
- RestoreInteriorClipping(aWindow);
- }
-
- /*
- * Given a widget in a window, set its selection state to 0 or 1 (selected)
- * and graphically draw the selection state now.
- */
-
- void SelectWidget(WidgetHandle item, int selected)
- {
- if ((selected!=0) ^ ((*item)->isSelected!=0)) { // Only if this is an actual change
- (*item)->isSelected = selected;
- SetInteriorClipping((*item)->itsWindow);
- DrawWidget(item);
- RestoreInteriorClipping((*item)->itsWindow);
- }
- }
-
- /*
- * Update our window and widget position table entries for the given window,
- * or for all windows if w is NIL. Returns number of windows in table.
- */
-
- short RecordPositions(WindowPtr w)
- {
- short i,k=0; WidgetHandle item;
-
- // For each current window in our table...
- for (i=0; i<MAXWINDOWS; i++)
- if (windows[i]) {
- k++;
- // If we've matched given window, or we're doing all of them...
- if ((windows[i]==w || w==NIL)) {
-
- // Save widget position (local coords) for re-opening
- item = (WidgetHandle)GetWRefCon(windows[i]);
- windowWidgetPosition[i] = (*item)->position;
-
- // Save global position of window on desktop for re-opening
- windowPosition[i] = windows[i]->portRect;
- LocalToGlobalRect(windows[i],&windowPosition[i]);
- }
- }
-
- return(k);
- }
-
- /*
- * Close the given window, disposing of its widget and zooming back to
- * the widget whence it came, if such widget is in some other window.
- * Delivers the widget that it zooms into, or NIL.
- */
-
- WidgetHandle CloseWidgetWindow(WindowPtr w)
- {
- short i; WidgetHandle closeItem = NIL;
-
- RecordPositions(w);
-
- if (w) {
- // Find the entry in table, mark it free, and ditch the given window
- for (i=0; i<MAXWINDOWS; i++) {
- if (windows[i] == w) {
- closeItem = CloseZoom(w);
- DisposeWindow(w);
- windows[i] = NIL;
- break;
- }
- }
- }
-
- return(closeItem);
- }
-
- /*
- * Determine if the given window was opened from a widget in some other window,
- * and if so, zoom back to the widget position after hiding the window.
- */
-
- WidgetHandle CloseZoom(WindowPtr w)
- {
- Rect startBox = (*((WindowPeek)w)->strucRgn)->rgnBBox;
- Rect endBox; WindowPeek wp;
- WidgetHandle item,closeItem=NIL; ZoomFrame start,end; ZoomFrameHandle zoomArray;
-
- SetRect(&endBox,0,0,0,0);
- wp = (WindowPeek)FrontWindow();
- while (wp) {
- closeItem = (WidgetHandle)GetWRefCon((WindowPtr)wp);
- // If not desk accessory and item window is this window
- if (wp->windowKind>=0 && closeItem!=NIL && (*closeItem)->openWindow==w) {
- // Detach item from its window, which is about to close
- (*closeItem)->openWindow = NIL;
- endBox = (*closeItem)->position;
- break;
- }
- wp = wp->nextWindow;
- }
-
- item = (WidgetHandle)GetWRefCon(w);
- DisposeHandle((Handle)item);
-
- // Precalculate the multi-window zoom information before hiding window
-
- start.frame = startBox; start.win = w;
- end.frame = endBox; end.win = (WindowPtr)wp;
- start.thickness = end.thickness = lineThick;
- zoomArray = NewZoom(&end,&start,FALSE,zoomStyle-OM_NoZooms);
-
- HideWindow(w);
-
- // Do the various flavors of zooming
-
- if (!EmptyRect(&endBox)) {
- UpdateAllWindows();
- //DoUpdate((WindowPtr)wp); // Make widget visible if it's behind closed window
- switch(zoomStyle) {
- case OM_NoZooms:
- break;
- case OM_StandardZooms:
- LocalToGlobalRect((WindowPtr)wp,&endBox);
- ZoomCenterRect(&startBox,&endBox,lineThick,speed,qSize);
- break;
- default:
- FrameEvadingZoom(zoomArray,speed,qSize);
- break;
- }
- }
-
- DisposeZoom(zoomArray);
- return(closeItem);
- }
-
- /*
- * Called for a key down event
- */
-
- int IsDoubleClick(Point *pt, long *time, int tol)
- {
- int ans = FALSE;
- static long lastTime; static Point thePt;
-
- if (*time-lastTime < GetDblTime()) {
- Rect box;
- SetRect(&box,thePt.h-tol,thePt.v-tol,thePt.h+tol,thePt.v+tol);
- ans = PtInRect(*pt,&box);
- lastTime = 0;
- thePt.h = thePt.v = -16000;
- }
- else {
- lastTime = *time;
- thePt = *pt;
- }
- return(ans);
- }
-
- int DoKeyDown()
- {
- int ch = (unsigned)(myEvent.message & charCodeMask);
-
- if (myEvent.modifiers & cmdKey) {
- return( DoMenu(MenuKey(ch),myEvent.modifiers) );
- }
-
- return(FALSE);
- }
-
- int DoMenu(long choice, short modifiers)
- {
- short menuID = HiWord(choice);
- short menuCh = LoWord(choice);
- short i,quitting = FALSE;
- short newThick,newSpeed,newQueue;
- WindowPtr w;
-
- switch(menuID) {
- case appleMenuID:
- DoAppleMenu(menuCh);
- break;
- case fileMenuID:
- switch(menuCh) {
- case FM_New:
- NewWidgetWindow();
- break;
- case FM_Open:
- /* Never happens: heirarchical */
- break;
- case FM_Close:
- /* Never happens: heirarchical */
- break;
- case FM_CloseAll:
- CloseAllWindows(FALSE);
- break;
- case FM_Quit:
- quitting = TRUE;
- break;
- }
- break;
- case editMenuID:
- switch(menuCh) {
- case EM_SelectAll:
- w = FrontWindow();
- if (w) {
- WidgetHandle item = (WidgetHandle)GetWRefCon(w);
- SelectWidget(item,TRUE);
- }
- break;
- case EM_SendBehind:
- w = FrontWindow();
- if (w) SendBehind(w,NIL);
- break;
- }
- break;
- case demoMenuID:
- switch(menuCh) {
- case DM_SaveDemo:
- RecordCurrentDemo(modifiers);
- break;
- case DM____2:
- break;
- case DM_None:
- CheckItem(demoMenu,theDemo,FALSE);
- CheckItem(demoMenu,theDemo = menuCh,TRUE);
- break;
- default:
- // Command is name of 'DEMO' resource with window config in it
- InstallDemo(menuCh);
- break;
- }
- break;
- case optionsMenuID:
- switch(menuCh) {
- case OM_SetLine:
- newThick = GetLineThickOrSpeed(lineThick,0);
- if (newThick > 0) lineThick = newThick;
- break;
- case OM_SetSpeed:
- newSpeed = GetLineThickOrSpeed(speed,1);
- if (newSpeed >= 0) speed = newSpeed;
- break;
- case OM_SetQueue:
- newQueue = GetLineThickOrSpeed(qSize,2);
- if (newQueue > 0) qSize = newQueue;
- break;
-
- case OM_NoZooms:
- case OM_StandardZooms:
- case OM_OneWindowDive:
- case OM_FrameEvading:
- CheckItem(optionsMenu,zoomStyle,FALSE);
- CheckItem(optionsMenu,zoomStyle = menuCh,TRUE);
- firstTime = FALSE;
- break;
- }
- break;
- case windowMenuID:
- case openWindowMenuID:
- case closeWindowMenuID:
- for (i=0; i<MAXWINDOWS; i++)
- if (windows[i] && --menuCh==0) {
- switch(menuID) {
- case windowMenuID:
- SelectWindow(windows[i]);
- break;
- case openWindowMenuID:
- OpenWidgetWindow(windows[i]);
- break;
- case closeWindowMenuID:
- CloseWidgetWindow(windows[i]);
- break;
- }
- break;
- }
- break;
- }
-
- HiliteMenu(0);
- return(quitting);
- }
-
- static void FixMenus()
- {
- WindowPtr w = FrontWindow();
- short i,n,k;
-
- if (w) EnableItem(fileMenu,FM_Open);
- else DisableItem(fileMenu,FM_Open);
-
- if (w) EnableItem(fileMenu,FM_Close);
- else DisableItem(fileMenu,FM_Close);
-
- if (w) EnableItem(fileMenu,FM_CloseAll);
- else DisableItem(fileMenu,FM_CloseAll);
-
- for (i=EM_Undo; i<=EM_Paste; i++)
- DisableItem(editMenu,i);
- if (w) EnableItem(editMenu,EM_SelectAll);
- else DisableItem(editMenu,EM_SelectAll);
- if (w) EnableItem(editMenu,0);
- else DisableItem(editMenu,0);
-
- if (theDemo == DM_None) DisableItem(demoMenu,DM_SaveDemo);
- else EnableItem(demoMenu,DM_SaveDemo);
-
- // Rebuild the window menus
-
- n = CountMItems(windowMenu);
- while (n > 0) {
- DeleteMenuItem(windowMenu,n);
- DeleteMenuItem(openWindowMenu,n);
- DeleteMenuItem(closeWindowMenu,n);
- n--;
- }
-
- if (w) EnableItem(windowMenu,0);
- else DisableItem(windowMenu,0);
-
- k = 1;
- for (i=0; i<MAXWINDOWS; i++)
- if (windows[i]) {
- WindowPeek wp = (WindowPeek)windows[i];
- HLock((Handle)wp->titleHandle);
- AppendMenu(windowMenu,*wp->titleHandle);
- AppendMenu(openWindowMenu,*wp->titleHandle);
- AppendMenu(closeWindowMenu,*wp->titleHandle);
- if (windows[i] == FrontWindow()) {
- SetItemMark(windowMenu,k,'•');
- SetItemCmd(openWindowMenu,k,'O');
- SetItemCmd(closeWindowMenu,k,'W');
- }
- HUnlock((Handle)wp->titleHandle);
- k++;
- }
- DrawMenuBar();
- }
-
- /*
- * Deal with a user choice from the Apple Menu: if not choosing "About Resorcerer..."
- * then it's a Desk Accessory to be opened.
- */
-
- static void DoAppleMenu(int choice)
- {
- Byte accName[256];
-
- switch(choice) {
- case AM_About:
- if (thisMac.hasColorQD)
- Alert(aboutBoxAlertID,NIL);
- else
- Alert(BWaboutBoxAlertID,NIL);
- break;
- default:
- GetItem(appleMenu,choice,accName);
- OpenDeskAcc(accName);
- break;
- }
- }
-
- /*
- * Grow a window to a new size in response to click in grow box
- */
-
- void DoGrow(WindowPtr window)
- {
- Rect r;
- long newSize; int x,y;
-
- r = qd.screenBits.bounds;
- SetRect(&r,32,32,r.right-r.left,r.bottom-r.top);
- newSize = GrowWindow(window,myEvent.where,&r);
- if (newSize) {
- x = LoWord(newSize); y = HiWord(newSize);
- SizeWindow(window,x,y,TRUE);
- PushPort(window);
- EraseRect(&window->portRect);
- DrawGrowIcon(window);
- r = *SetInteriorClipping(window);
- InvalRect(&r);
- RestoreInteriorClipping(window);
- PopPort();
- }
- }
-
- void RebuildDemoMenu()
- {
- short n;
-
- // Empty the menu, except for the first "No demo" entry, and the line after it
- for (n=CountMItems(demoMenu); n>DM_None; n--)
- DeleteMenuItem(demoMenu,n);
-
- // Append the names of all 'DEMO' resources to menu
- AddResMenu(demoMenu,'DEMO');
- }
-
- /*
- * Given a choice from the Demo menu (kDemo), retrieve the resource and use it
- * to build a set of windows and widgets.
- */
-
- void InstallDemo(short kDemo)
- {
- StartWindowHandle demo; StartWindow win; short i,k,numWins;
- WindowPtr w; Byte str[256]; int newOrdering,oldZoom,doClose;
-
- if (firstTime) {
- if (zoomStyle == OM_NoZooms) {
- CheckItem(optionsMenu,zoomStyle,FALSE);
- CheckItem(optionsMenu,zoomStyle=OM_FrameEvading,TRUE);
- }
- firstTime = FALSE;
- }
-
- // Turn off any zooming while throwing away all current windows
-
- oldZoom = zoomStyle;
- zoomStyle = OM_NoZooms;
- CloseAllWindows(TRUE); // Resets entire position table
- zoomStyle = oldZoom;
-
- Wait(20);
-
- GetItem(demoMenu,kDemo,str);
- demo = (StartWindowHandle)Get1NamedResource('DEMO',str);
- if (demo) {
-
- numWins = (*demo)->numWins;
- if (numWins > MAXWINDOWS) numWins = MAXWINDOWS;
- if (numWins == 0)
- NewWidgetWindow();
- else {
- newOrdering = doClose = FALSE;
- for (i=0; i<numWins; i++) {
- win = (*demo)->win[i];
-
- windowPosition[i] = win.position;
- windowWidgetPosition[i] = win.fezBounds;
- if (i == 0)
- w = CreateWidgetWindow(i,&win.position,&win.fezBounds,TRUE);
- else
- w = OpenWidgetWindow(windows[i-1]);
-
- if (win.finalOrdering != (numWins-1-i))
- newOrdering = TRUE;
- if (win.closeOrdering != -1)
- doClose = TRUE;
- }
-
- /* Now rearrange open windows into final ordering if different */
- if (newOrdering)
- for (k=numWins-1; k>=0; k--)
- for (i=0; i<numWins; i++) {
- if ((*demo)->win[i].finalOrdering == k) {
- SelectWindow(windows[i]);
- DoUpdate(windows[i]);
- }
- }
-
- // And close any windows in the order specified
- if (doClose) {
- WidgetHandle closeItem = NIL;
- Wait(40);
- for (k=numWins-1; k>=0 && closeItem==NIL; k--)
- for (i=0; i<numWins; i++) {
- if ((*demo)->win[i].closeOrdering == k) {
- closeItem = CloseWidgetWindow(windows[i]);
- break;
- }
- }
- if (closeItem) {
- Wait(40);
- OpenWidgetWindow((*closeItem)->itsWindow);
- }
- }
- }
-
- CheckItem(demoMenu,theDemo,FALSE);
- CheckItem(demoMenu,theDemo = kDemo,TRUE);
- }
- }
-
- /*
- * Resize the demo resource for the current demo, and place into it the current
- * positions and ordering of all the windows and their widgets. If modifiers
- * has option key on, record the front most window as to-be-closed.
- */
-
- void RecordCurrentDemo(short modifiers)
- {
- StartWindowHandle demo; StartWindow *win;
- short i,k,numWins; WindowPtr w; Byte str[256];
-
- if (theDemo == DM_None) return;
-
- numWins = RecordPositions(NIL);
-
- GetItem(demoMenu,theDemo,str);
- demo = (StartWindowHandle)Get1NamedResource('DEMO',str);
- if (demo) {
-
- SetHandleSize((Handle)demo, sizeof(short) + numWins*sizeof(StartWindow));
- if (MemError()) return;
-
- /* Save the positions of windows and widgets into resource */
-
- HLock((Handle)demo);
- (*demo)->numWins = numWins;
- win = (*demo)->win;
- for (i=0; i<MAXWINDOWS; i++)
- if (windows[i]) {
- win->position = windowPosition[i];
- win->fezBounds = windowWidgetPosition[i];
- win->closeOrdering = (windows[i]==FrontWindow() && (modifiers&optionKey)!=0) ? (numWins-1) : -1;
- for (k=0,w=FrontWindow(); w; w=(WindowPtr)((WindowPeek)w)->nextWindow,k++)
- if (w == windows[i]) {
- win->finalOrdering = k;
- break;
- }
- win++;
- }
- HUnlock((Handle)demo);
-
- ChangedResource((Handle)demo);
- UpdateResFile(CurResFile());
- }
- }
-
- void CloseAllWindows(int reset)
- {
- WindowPtr w; short i;
-
- for (w=FrontWindow(); w; w=FrontWindow())
- CloseWidgetWindow(w);
-
- if (reset)
- for (i=0; i<MAXWINDOWS; i++) {
- windows[i] = NIL;
- SetRect(&windowPosition[i],0,0,0,0);
- windowWidgetPosition[i] = stdWidgetPosition;
- }
- }
-
-
- /////////////////////////////////////////////////////////////////////////////////////////////////
-
- /*
- * Deliver the index of the first free window slot in table. Delivers -1 if none.
- */
-
- short NextFreeWindowIndex()
- {
- short index;
-
- for (index=0; index<MAXWINDOWS; index++)
- if (windows[index] == NIL)
- return(index);
- return(-1);
- }
-
- /*
- * Create a new color window at the given position, and add a widget at the
- * given position, or in the standard initial position if widgetSpot is NIL.
- * The window title is built from the given index.
- * Delivers the window's pointer, and does not show the window.
- */
-
- WindowPtr CreateWidgetWindow(short index, Rect *bounds, Rect *widgetSpot, int show)
- {
- WindowPtr w=NIL; WidgetHandle item; Byte *title;
-
- if (index>=0 && index<MAXWINDOWS) {
-
- // Get a new widget first
- item = (WidgetHandle)NewHandleClear(sizeof(Widget));
- if (item) {
-
- // Initialize widget
- if (widgetSpot) (*item)->position = *widgetSpot;
- else (*item)->position = stdWidgetPosition;
- (*item)->isSelected = FALSE;
-
- // Create the title using index
- title = "\pFez xx";
- if (index < 10) { title[5] = '0'+index; title[0] = 5; }
- else { title[5] = '0'+index/10; title[6] = '0'+index%10; title[0] = 6; }
-
- w = NewCWindow(NIL,bounds,title,FALSE,zoomDocProc,(WindowPtr)-1,TRUE,(long)item);
- if (w) {
- (*item)->itsWindow = w;
- windows[index] = w;
- windowPosition[index] = *bounds;
- windowWidgetPosition[index] = (*item)->position;
- if (show) { ShowWindow(w); DoUpdate(w); }
- }
- else
- DisposeHandle((Handle)item);
- }
- }
-
- return(w);
- }
-
- /*
- * Given an index, compute the bounds of its window using a formula
- * that staggers the windows in groups of 8 on the main screen.
- */
-
- Rect *StaggeredWindowBounds(short index)
- {
- static Rect ans; short x,y; Point pt;
-
- x = index / 8;
- y = index % 8;
- pt.h = 4;
- pt.v = 4 + GetMBarHeight();
- pt.h += 5 + 30*x + 5*y;
- pt.v += 20 + 20*y + 5*x;
- SetRect(&ans,100,100,300,300);
- OffsetRect(&ans,pt.h-ans.left,pt.v-ans.top);
-
- return(&ans);
- }
-
- /*
- * Create a new widget window that isn't attached to any previous widget and
- * which gets placed at a standard position.
- */
-
- WindowPtr NewWidgetWindow()
- {
- WindowPtr w=NIL; short index;
-
- index = NextFreeWindowIndex();
- if (index >= 0)
- w = CreateWidgetWindow(index,StaggeredWindowBounds(index),kDefaultPosition,TRUE);
- else
- SysBeep(1);
-
- return(w);
- }
-
- /*
- * Open another widget window on the desk top. If parentWindow is non-NIL,
- * then the window being opened belongs to the widget in parent window.
- * Any zooming to be done gets done here. Delivers the window's pointer.
- */
-
- WindowPtr OpenWidgetWindow(WindowPtr parentWindow)
- {
- Rect bounds,rect,*initPos; short index;
- WindowPtr w=NIL; WidgetHandle item;
- ZoomFrame start,end; ZoomFrameHandle zoomArray;
-
- if (parentWindow) {
- // Check first for window whose widget is already in this window
- item = (WidgetHandle)GetWRefCon(parentWindow);
- if ((*item)->openWindow)
- SelectWindow(w = (*item)->openWindow);
- else {
- // Widget not yet opened: open first window slot for it
- index = NextFreeWindowIndex();
- if (index >= 0) {
-
- if (EmptyRect(&windowPosition[index])) {
- bounds = *StaggeredWindowBounds(index);
- initPos = kDefaultPosition;
- }
- else {
- bounds = windowPosition[index];
- initPos = &windowWidgetPosition[index];
- }
- w = CreateWidgetWindow(index,&bounds,initPos,FALSE);
- if (w) {
- // Attach window to its widget
- (*item)->openWindow = w;
- rect = (*item)->position; // Of widget being opened, not new one
-
- // Precompute the zoom information and zoom before showing window
- start.frame = rect; start.win = parentWindow; start.thickness = lineThick;
- end.frame = bounds; end.win = w; end.thickness = lineThick;
- zoomArray = NewZoom(&start,&end,TRUE,zoomStyle-OM_NoZooms);
-
- switch(zoomStyle) {
- case OM_NoZooms:
- break;
- case OM_StandardZooms:
- LocalToGlobalRect(parentWindow,&rect);
- ZoomCenterRect(&rect,&bounds,lineThick,speed,qSize);
- break;
- default:
- FrameEvadingZoom(zoomArray,speed,qSize);
- break;
- }
-
- ShowWindow(w);
- DoUpdate(w);
- DisposeZoom(zoomArray);
- }
- }
- else
- SysBeep(1);
- }
- }
- else
- w = NewWidgetWindow();
-
- return(w);
- }
-
- void UpdateAllWindows()
- {
- WindowPeek wp;
-
- for (wp=(WindowPeek)FrontWindow(); wp; wp=wp->nextWindow)
- if (wp->visible)
- DoUpdate((WindowPtr)wp);
- }
-
-